import asyncio
import datetime


MAX_CANDLES = 200

OPEN  = 0
HIGH  = 0
LOW   = 0
CLOSE = 0

class Candlestick:
  def __init__(self, ticker, interval):
    self.values   = []
    self.latest   = None
    self.interval = interval

    self._ticker   = ticker
    self._event    = asyncio.Event()

    asyncio.create_task(self._refresh_and_start())

  async def _refresh_and_start(self):
    self.values = await self._fetch(datetime.datetime.now(tz=datetime.timezone.utc))
    asyncio.create_task(self._ticker_watcher())
    asyncio.create_task(self._main())

  async def _fetch(self, data, depth = 0, rem = MAX_CANDLES):
    assert(False)

  async def _ticker_watcher(self):
    while True:
      await self._ticker.wait()
      v = self._ticker.price
      if self.latest is None:
        self.latest = [v, -1e100, 1e100, None]
      self.latest[1] = max(self.latest[1], v)
      self.latest[2] = min(self.latest[2], v)
      self.latest[3] = v

  async def _main(self):
    while True:
      await asyncio.sleep(self.interval)
      if self.latest is None:
        if len(self.values) == 0:
          continue
        self.latest = self.values[0]
      n = min(MAX_CANDLES-1, len(self.values))
      self.values = [self.latest, *self.values[0:n]]
      self.latest = None
      self._event.set()
      self._event.clear()

  async def wait(self):
    await self._event.wait()

  def SMA(self, period, offset=0, type = CLOSE):
    sum = 0
    end = min(period+offset, len(self.values))
    for i in range(offset, end):
      sum += self.values[i][type]
    return sum / (end - offset)

  def EMA(self, period, offset=0, type = CLOSE):
    end = min(period+offset, len(self.values))
    n   = end - offset

    ret = 0
    for i in range(offset, end):
      ret += self.values[i][type]
    ret /= n
    for i in range(offset, end):
      ret += (2/(n+1)) * (self.values[i][type] - ret)
    return ret
